package com.acme.concurrent.executor;

import java.io.File;
import java.io.FileFilter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Gregory Sobko
 */
class FileCrawler implements Runnable {
    private final FileQueuePool fileQueue;
    private final FileFilter fileFilter;
    private final File root;
    private final ExecutorService executorService;
    private final AtomicInteger countDown;


    public FileCrawler(FileQueuePool fileQueue,
                       final FileFilter fileFilter,
                       File root,
                       ExecutorService executorService
    ) {
        this(fileQueue, fileFilter, root, executorService, new AtomicInteger(1));
    }

    private FileCrawler(FileQueuePool fileQueue,
                       final FileFilter fileFilter,
                       File root,
                       ExecutorService executorService,
                       AtomicInteger countDown) {
        this.fileQueue = fileQueue;
        this.root = root;
        this.fileFilter = new FileFilter() {
            public boolean accept(File f) {
                return f.isDirectory() || fileFilter.accept(f);
            }
        };
        this.executorService = executorService;
        this.countDown = countDown;
    }

    private boolean alreadyIndexed(File f) {
        return false;
    }

    public void run() {
        try {
            crawl(root);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } catch (IllegalStateException e){
            System.err.println("Queue pool is closed! Cannot put any files in it =(");
        }finally {
            if(countDown.decrementAndGet() == 0){
                fileQueue.signalProducerDone();
                System.out.println("Crawler thread is done!");
            }

        }
    }

    private void crawl(File root) throws InterruptedException {
        File[] entries = root.listFiles(fileFilter);
        if (entries != null) {
            for (File entry : entries)
                if (entry.isDirectory()){
                    countDown.getAndIncrement();
                    executorService.submit(new FileCrawler(fileQueue, fileFilter, entry, executorService, countDown));
                }
                else if (!alreadyIndexed(entry))
                    fileQueue.put(entry);
        }

    }
}
